<!-- 自动化实验-模板创建任务 -->
<template>
  <!-- 顶部搜索区 -->
  <div class="main-app" v-loading="loading">
    <el-breadcrumb separator-class="el-icon-arrow-right" style="margin-top: 5px; margin-bottom: 15px;">
      <el-breadcrumb-item :to="{path:'/'}">{{$t('common.nav.home')}}</el-breadcrumb-item>
      <el-breadcrumb-item>{{$t('common.nav.automationExperiment')}}</el-breadcrumb-item>
      <el-breadcrumb-item>{{$t('common.nav.templateCreateTask')}}</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 数据列表区 -->
    <el-card class="box-card" style="margin-top: 1%;">
      <!-- 搜索条件 -->
      <el-form :inline="true" :model="searchParam" class="form-inline" style="margin-bottom: -1%;">
        <el-form-item :label="$t('common.label.expTemplateName')+':'">
          <el-input v-model="searchParam.name" clearable />
        </el-form-item>
        <el-form-item :label="$t('common.label.expTemplateNumber')+':'">
          <el-input v-model="searchParam.number" clearable />
        </el-form-item>
        <el-form-item :label="$t('common.label.expTemplateAuth')+':'">
          <el-select v-model="searchParam.type" :placeholder="$t('common.placeholder.pleaseSelect')">
            <el-option :label="$t('common.label.all')" value="10,20" />
            <el-option :label="$t('common.label.public')" value="10" />
            <el-option :label="$t('common.label.private')" value="20" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" @click="search">{{$t('common.button.search')}}</el-button>
        </el-form-item>
        <el-form-item>
          <el-button icon="el-icon-refresh-right" @click="reset">{{$t('common.button.reset')}}</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <el-row :gutter="10" style="margin-top: 10px;">
      <el-col :span="5">
        <el-card class="box-card" style="height: 78vh;">
          <div class="titie-bar"><span>{{$t('common.title.expTemplateList')}}</span></div>
          <!-- 数据菜单 -->
          <!-- <el-menu :default-active="activeMenuIndex" style="margin-top: 10px;" @select="handleSelect">
            <el-menu-item v-for="(item,index) in templateData" :key="index" :index="item.id" class="text-item">
              <i class="el-icon-document" style="margin-left: -10px;"></i>
              <span slot="title">{{item.name}} ({{item.number}})</span>
            </el-menu-item>
          </el-menu> -->
          <!-- 数据表格 -->
          <el-table id="table" ref="multipleTable" tooltip-effect="dark" style="width: 100%; margin-top: 10px;" stripe :show-header="false" :data="tableData">
            <el-table-column prop="name" :label="$t('common.label.name')">
              <template slot-scope="scope">
                <div @click="handleSelect(scope.row.id, '')">
                  <i class="el-icon-document"></i>
                  {{scope.row.name}} ({{scope.row.number}})
                </div>
              </template>
            </el-table-column>
            <el-table-column align="center" width="50">
              <template slot-scope="scope">
                <i class="el-icon-rank handle"></i>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </el-col>
      <el-col :span="19">
        <el-card class="box-card" style="height: 78vh;">
          <!-- 实验流程概览-标题 -->
          <el-row :gutter="110">
            <el-col :span="20">
              <div class="titie-bar"><span>{{$t('common.title.expProcessOverview')}}</span></div>
            </el-col>
            <el-col :span="4">
              <!-- <el-button type="primary" plain icon="el-icon-receiving" @click="operation($t('common.button.importTemplate'))">{{$t('common.button.importTemplate')}}</el-button> -->
              <el-button type="primary" icon="el-icon-plus" @click="operation($t('common.button.addTemplate'))">{{$t('common.button.addTemplate')}}</el-button>
            </el-col>
          </el-row>
          <!-- 实验流程概览-Tab栏 -->
          <el-row>
            <el-tabs v-model="activeName" style="margin: 5px;" @tab-click="handleTabClick">
              <el-tab-pane :label="$t('common.label.singleTask')" name="single-task" tag="10"></el-tab-pane>
              <el-tab-pane :label="$t('common.label.parallelTask')" name="parallel-task" tag="20"></el-tab-pane>
              <el-tab-pane :label="$t('common.label.iterationOptimizeTask')" name="iteration-optimize-task" tag="30"></el-tab-pane>
            </el-tabs>
            <div class="antv-wrapper">
              <div class="wrapper-canvas" id="wrapper"></div>
            </div>
          </el-row>
          <!-- 实验流程概览-底部编辑按钮 -->
          <el-row v-if="flowPathData.length > 0" :gutter="20" style="margin-top: -32%; margin-left: 54.5vw;">
            <el-col>
              <el-button type="primary" plain icon="el-icon-edit-outline" @click="operation($t('common.button.edit'))">{{$t('common.button.edit')}}</el-button>
              <el-button type="primary" icon="el-icon-s-promotion" @click="operation($t('common.button.submitExp'))" :disabled="!thisSelFlowPathData.id">{{$t('common.button.submitExp')}}</el-button>
            </el-col>
          </el-row>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script>
  // 引用 Sortable
  import Sortable from 'sortablejs'
  import { Graph, Shape } from '@antv/x6'
  import { configNodePorts } from '@/utils/antvSetting'
  import { pageMixin } from "../../../mixins/index";
  import {
    CheckExperimentQueue,
    CreateExperimentNumber,
    ExperimentTemplateList,
    ExperimentTemplateDetail,
    ExperimentTemplateConfigDetail,
    UpdateExperimentTemplateSort,
  } from "../../../api/experiment.js";
  import {
    SubmitExperimentRecord,
  } from "../../../api/record.js";
  export default {
    // 页面公共变量
    data() {
      return {
        // 搜索条件参数
        searchParam: {
          name: "",
          number: "",
          type: "10,20"
        },
        activeMenuIndex: "",              // 默认选中的菜单索引
        activeName: "single-task",        // 当前选中的Tab页面
        activeType: "10",                 // 当前选中的实验流程类型
        dialogVisible: false,             // 是否隐藏提示框
        templateData: [],                 // 实验模板数据
        nodeConfigData: [],               // 实验模板关联配置数据
        flowPathData: [],                 // 实验流程数据
        thisSelTemplateData: {},          // 当前选中的实验模板数据
        thisSelFlowPathData: {},          // 当前选中的实验流程数据
        graph:[],                         // 任务流程图配置
      };
    },
    // 页面创建完成事件
    async created() {
      await this.init();
      this.initGraph();

      // 检查实验任务队列
      await CheckExperimentQueue().then((res) => {});
    },
    // 数据过滤器
    filters: {
      // 转换日期显示格式
      parseDate(value) {
        if (value) {
          return value.replace("T", " ");
        }
      },
    },
    // 表格分页属性配置
    mixins: [pageMixin],
    // 页面相关方法
    methods: {
      // 初始化加载事件
      async init() {
        this.templateData = [];     // 清空数据源
        this.flowPathData = [];
        this.loading = true;        // 打开加载框

        // 获取列表数据
        await ExperimentTemplateList({
          page: null,
          limit: null,
          Name: this.searchParam.name,
          Number: this.searchParam.number,
          Type: this.searchParam.type
        }).then(res => {
          if (res.success === true && res.data.length > 0) {
            this.tableData = res.data;
            this.rowDrop();             // 挂载更改表格排序事件

            this.templateData = res.data;
            this.thisSelTemplateData = this.templateData[0];
            this.activeMenuIndex = this.templateData[0].id;
            this.getFlowPathData(this.templateData[0].id);
          } else {
            this.graph.clearCells();   // 清空全部节点
          }
        });

        this.loading = false;       // 关闭加载框
      },
      // 表格重置事件
      async reset() {
        this.searchParam = {
          name: "",
          number: "",
          type: "10,20"
        };
        this.graph.clearCells();    // 清空全部节点
        await this.init();
      },
      // 操作功能按钮点击事件
      operation(value) {
        switch (value) {
          // 导入模板
          case this.$t('common.button.importTemplate'):
            this.importExpTemplate();
            break;
          // 新建模板
          case this.$t('common.button.addTemplate'):
            this.$router.push(`template_create_task/create`);
            break;
          // 编辑
          case this.$t('common.button.edit'):
            this.$router.push(`template_create_task/edit/${this.thisSelTemplateData.id}/${this.thisSelFlowPathData.id}/${this.activeType}`);
            break;
          // 提交实验
          case this.$t('common.button.submitExp'):
            this.submitExperiment();
            break;
        }
      },
      // 数据行更改事件
      rowDrop() {
        //const el = document.querySelector('#table .el-table__body-wrapper tbody')
        const el = document.querySelectorAll('.el-table__body-wrapper > table > tbody')[0];
        const sortable = new Sortable(el, {
          animation: 150,
          handle: '.handle',
          ghostClass: 'blue-background-class',
          onEnd: evt => {
            // 更改数据源数组顺序
            this.tableData.splice(evt.newIndex, 0, this.tableData.splice(evt.oldIndex, 1)[0]);
            const newArray = this.tableData.slice(0);
            newArray.forEach((value, index) => {
              value.sort = index + 1; // 序号为index+1
              this.$set(newArray, index, value);

            	this.tableData = [];
            	this.$nextTick(() => {
            	  this.tableData = newArray ? newArray : [];
            	})
            });
            this.$nextTick(() => {
              // 保存更改至数据库
              this.updateSort(this.tableData);
            })
          }
        });
      },
      // 更改实验模板顺序
      async updateSort(tableData) {
        let tableSortData = [];
        tableData.forEach((value, index) => {
          tableSortData.push({
            Id: value.id,
            Value: value.sort.toString()
          });
        });
        //console.log(tableSortData);

        UpdateExperimentTemplateSort({ SetValueData: tableSortData }).then(res => {
          if (res.success === true) {
            this.$message({ type: 'success', message: this.$t('common.prompt.success.submit') });
          } else {
            this.$message({ type: 'error', message: msg });
          }
        });
      },
      // 菜单选择事件
      handleSelect(index, indexPath) {
        // 重置选中第一个Tab栏
        this.activeName = "single-task";

        // 获取实验流程数据
        this.getFlowPathData(index);
      },
      // Tab栏点击事件
      handleTabClick(tab, event) {
        // console.log(tab, event);
        // console.log(tab.$attrs.tag);
        this.thisSelFlowPathData = {};    // 保存当前选中的数据源
        this.activeType = tab.$attrs.tag;
        this.graph.clearCells();          // 清空当前画布全部节点

        let data = this.flowPathData.find(item => item.type === tab.$attrs.tag);
        if (data) {
          // 保存当前选中的数据源
          this.thisSelFlowPathData = data;

          // 更新画布渲染数据
          this.initGraphData(data);
        }
      },
      // 获取实验流程数据
      async getFlowPathData(id) {
        this.flowPathData = [];     // 清空数据源
        this.loading = true;        // 打开加载框

        // 获取数据
        await ExperimentTemplateDetail({
          Id: id
        }).then(res => {
          if (res.success === true) {
            // 保存当前选中的数据源
            this.thisSelTemplateData = res.data;
            this.flowPathData = res.data.configList;

            // 如果存在节点配置时则初始化实验流程概览数据
            if(res.data.configList.length > 0) {
              this.initGraphData(this.flowPathData[0]);
            }
          }
        });

        this.loading = false;       // 关闭加载框
      },
      // 导入实验流程模板
      importExpTemplate() {
        this.$message({type: 'info', message: this.$t('common.prompt.info.notYetOpen')});
      },
      // 提交实验
      async submitExperiment() {
        // 转换实验流程类型
        let flowPathTypeName = '';
        switch(this.thisSelFlowPathData.type) {
          case "10": {flowPathTypeName = this.$t('common.label.singleTask');} break;
          case "20": {flowPathTypeName = this.$t('common.label.parallelTask');} break;
          case "30": {flowPathTypeName = this.$t('common.label.iterationOptimizeTask');} break;
        }

        // 校验数据
        if(this.thisSelFlowPathData.flowPathConfig === "") {
          this.$message({type: 'error', message: this.$t('common.prompt.info.notYetConfigExpType')});
          return;
        }

        // 获取节点配置顺序数据
        const {cells: jsonArr} = this.graph.toJSON();
        let nodeData = [];
        jsonArr.filter(function(item) {
          try {
            if (item.data.type = "otherImage") {
              nodeData.push({
                NodeId: item.id,
                NodeName: item.attrs.label.text,
                NodeCreateTime: item.createTime,
              });
            }
          } catch { }
        });
        //console.log(nodeData);

        this.$confirm(this.$t('common.prompt.info.isSubmitExpToQueue'), this.$t('common.dialog.tip'), {
          confirmButtonText: this.$t('common.dialog.confirm'),
          cancelButtonText: this.$t('common.dialog.cancel'),
          type: 'warning'
        }).then(async () => {
          // 弹出长时间加载提示
          this.$message({type: 'info', message: this.$t('common.prompt.info.processingExpData'), duration: 10000, showClose: true});

          // 打开加载框
          this.loading = true;

          // 获取配置数据
          await ExperimentTemplateConfigDetail({
            Id: this.thisSelFlowPathData.id
          }).then(res => {
            if (res.success === true) {
              this.nodeConfigData = res.data2;
            }
          });

          let data = {
            ExpRecordData: {
              Name: `${this.thisSelTemplateData.name}-${flowPathTypeName}`,
              Number: this.thisSelTemplateData.number,
              Status: '10',
              ExpectedWorkingHours: parseInt(this.thisSelFlowPathData.expectedWorkingHours),
              Sort: 1,
              ExpStartTime: null,
              ExpEndTime: null,
              FlowPathConfig: this.thisSelFlowPathData.flowPathConfig,
              Remark: ""
            },
            NodeConfigData: this.nodeConfigData,
            ExpConfigNodeData: nodeData,
          };

          // 初始化实验任务编号
          await CreateExperimentNumber().then((res) => {
            data.ExpRecordData.Number = res.data;
          });

          // // 测试：查看已生成的表单内容，不提交数据
          // console.log(data)
          // return;

          // 提交数据
          const {success, msg} = await SubmitExperimentRecord(data);

          // 关闭加载框
          this.loading = false;

          // 显示返回结果
          if (success === true) {
            this.$message({type: 'success', message: this.$t('common.prompt.success.submitExp')});
            // 检查实验任务队列
            await CheckExperimentQueue().then((res) => {});
          } else {
            this.$message({type: 'error', message: msg});
          }
        }).catch(() => {})
      },
      // 初始化渲染画布
      initGraph() {
        this.graph = new Graph({
          container: document.getElementById('wrapper'),  // 容器
          height: 600,            // 画布默认高度
          grid: true,             // 网格线
          autoResize: true,       // 自动缩放，根据容自动更改画布大小
          mousewheel: false,      // 鼠标滚轮缩放
          interacting: false,
          // 启用画布拖拽
          panning: {
            enabled: true,
            //eventTypes: ['leftMouseDown', 'rightMouseDown', 'mouseWheel']
            eventTypes: []
          },
          connecting: {
            router: {
              name: 'manhattan',
              args: {padding: 1},
            },
            connector: {
              name: 'rounded',
              args: {radius: 8},
            },
            anchor: 'center',
            connectionPoint: 'anchor',
            allowBlank: false,
            snap: {radius: 20},
            createEdge() {
              return new Shape.Edge({
                attrs: {
                  line: {
                    stroke: '#A2B1C3',
                    strokeWidth: 2,
                    targetMarker: {name: 'block', width: 12, height: 8},
                  },
                },
                zIndex: 0,
              })
            }
          },
        });
        this.graph.enablePanning()   // 启用画布平移
        this.graph.zoom(-0.1);       // 减少缩放级别
      },
      // 更新画布渲染数据
      initGraphData(data) {
        this.thisSelFlowPathData = data;  // 保存当前选中的数据

        const portsGroups = configNodePorts().groups;
        const flowPathConfigData = eval(data.flowPathConfig);
        if (flowPathConfigData.length) {
          const jsonTemp = flowPathConfigData.map(item => {
            if (item.ports) item.ports.groups = portsGroups;
            return item;
          });
          this.graph.fromJSON(jsonTemp);  // 更新数据
          this.graph.centerContent();     // 画布内容居中
        }
      }
    },
  };
</script>

<style lang="scss" scoped>
// 顶部按钮绝对定位
.formbtn {text-align: right;}
// 数据表格区样式
.show-result {margin-top: 1%;}

/* 菜单样式 */
::v-deep .el-menu {border-right: solid 0px #e6e6e6;}
::v-deep .el-menu-item {font-size: 16px;}
/* 操作项开关样式 */
::v-deep .switch .el-switch__label {position: absolute;display: none;color: #fff;}
/* 打开时文字位置设置 */
::v-deep .switch .el-switch__label--right {z-index: 1;right: 5px;}
/* 关闭时文字位置设置 */
::v-deep .switch .el-switch__label--left {z-index: 1;left: 8px;}
/* 显示文字 */
::v-deep .switch .el-switch__label.is-active {display: block;}
::v-deep .switch.el-switch .el-switch__core,
::v-deep .el-switch .el-switch__label {width: 60px !important;}
/* 表格隔行换色样式 */
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td {background-color: #F2F2F2;}
/* 表格数据行高 */
::v-deep .el-table td {padding: 8px 0px;}
/* 表头背景色样式 */
::v-deep .el-table th {background-color: #DBEDEF !important;}
/* 表头数据行内线样式 */
::v-deep .el-table td,
.building-top .el-table th.is-leaf {border-bottom: 0px;}

// 流程图区样式
@keyframes ant-line {
  to {
    stroke-dashoffset: -1000
  }
}
.antv-wrapper {
  position: relative;
  height: 100vh;
  flex: 1;
  margin-top: -1%;
  .wrapper-canvas {
    height: 100%;
    width: 100%;
    position: relative;
  }
  .wrapper-tips {
    padding: 10px;
    display: flex;
    align-items: center;
    position: absolute;
    top: 0;
    left: 0;
    .wrapper-tips-item {
      span {
        padding-left: 10px;
        font-size: 12px;
      }
    }
  }
}

/* 自定义提示框样式 */
.dialog_diy {
  ::v-deep .el-dialog__wrapper {
    .el-dialog {
      .el-dialog__body {
        padding: 0px;
      }
      .el-dialog__header {padding: 0px;}
      .el-dialog__headerbtn {top: 5px;right: 5px;padding-top: 10px;}
      .el-dialog__headerbtn .el-dialog__close {color: #fff;height: 30px;width: 35px;}
      .el-dialog__headerbtn .el-dialog__close:hover {color: gray;}
    }
  }
}

// 区域标题样式
.titie-bar {
  width: 4px;
  height: 32px;
  border-radius: 2px;
  background-color: rgba(61, 171, 175, 1);
  margin: 5px 0 5px 0;
}

.titie-bar span {
  color: #0A0A0A;
  width: 80px;
  font-size: 22px;
  line-height: 32px;
  white-space: nowrap;
  overflow-wrap: break-word;
  margin-left: 15px;
}

// 设备状态区域样式
.device-status-panal {
  height: 400px;
  border-radius: 8px;
  box-shadow: 0px 2px 6px 0px rgba(39, 122, 160, 0.09);
  background-size: contain;
  background-position: center center;
  background-repeat: no-repeat;
  display: flex;
  flex-direction: column;
}

.device-status-panal-bg {
  background-image: url(../../../assets/icon/automation_experiment/task_overview/device_status_bg.png);
}

// 实景监控按钮样式
.monitor-btn {
  width: 140px;
  height: 40px;
  background-color: rgba(61, 171, 175, 1);
  border: 1px solid rgba(255, 255, 255, 1);
  box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.05);
  border-radius: 0px 8px 0px 16px;
  text-align: right;
  margin-top: -22px;
  margin-left: 35vw;
  margin-right: auto;
  display: flex;
  flex-direction: row;

  img {
    width: 24px;
    height: 24px;
    margin: 9px 0 0 24px;
  }

  span {
    width: 64px;
    height: 22px;
    color: rgba(255, 255, 255, 1);
    font-size: 16px;
    font-weight: 500;
    text-align: left;
    white-space: nowrap;
    overflow-wrap: break-word;
    line-height: 22px;
    margin: 9px 24px 0 0;
  }
}

// 统计区域样式
.statistics-panal {
  border-radius: 8px;
  box-shadow: 0px 2px 6px 0px rgba(39, 122, 160, 0.09);
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  display: flex;
  flex-direction: column;
}

.statistics-panal-bg-1 {
  background-image: url(../../../assets/icon/automation_experiment/task_overview/panal_bg_1.png);
}

.statistics-panal-bg-2 {
  background-image: url(../../../assets/icon/automation_experiment/task_overview/panal_bg_2.png);
}

// 设备工作统计区域样式
.work-statistics-panal {
  text-align: left;
  font-weight: 500;
  white-space: nowrap;
  overflow-wrap: break-word;

  .title {
    color: rgba(51, 51, 51, 1);
    width: 200px;
    height: 28px;
    font-size: 20px;
    line-height: 80px;
  }

  .content {
    color: rgba(63, 171, 175, 1);
    font-size: 40px;
    font-weight: 500;
    line-height: 110px;

    span:nth-of-type(2),
    span:nth-of-type(4),
    span:nth-of-type(6) {
      font-size: 24px;
    }
  }
}
</style>
